﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils
{
    public enum HtmlTagType
    {
        /// <summary>
        /// 无法确定类型。
        /// </summary>
        UnKnow,
        /// <summary>
        /// 类似：&lt;html&gt;
        /// </summary>
        Start,
        /// <summary>
        /// 类似：&lt;/html&gt;
        /// </summary>
        End,
        /// <summary>
        /// 类似：&lt;html/&gt;
        /// </summary>
        Whole,
    }

    public class HtmlTag
    {
        public HtmlTag(string outHtmlText)
        {
            this.outHtmlText = outHtmlText.Trim(new char[] { ' ', '　', '\t', });
        }

        private string outHtmlText = "";

        public string OutHtmlText { get { return outHtmlText; } }

        /// <summary>
        /// 标签类型。
        /// </summary>
        public HtmlTagType TagType
        {
            get
            {

                if (string.IsNullOrWhiteSpace(outHtmlText)) return HtmlTagType.UnKnow;
                if (outHtmlText.StartsWith("<") == false) return HtmlTagType.UnKnow;
                if (outHtmlText.EndsWith(">") == false) return HtmlTagType.UnKnow;

                if (outHtmlText.StartsWith("</")) return HtmlTagType.End;
                if (outHtmlText.EndsWith("/>")) return HtmlTagType.Whole;

                return HtmlTagType.Start;
            }
        }

        /// <summary>
        /// 标签名：&lt;html a='atext' b='btext'/>  中的 'html'。
        /// </summary>
        public string Name
        {
            get
            {
                var regStart = new Regex(@"(?<=(^<))[a-zA-Z]{1,}[a-zA-Z0-9\-_]{0,}(?=((/{0,1}>)|([ 　\t]{1,})))");
                var m = regStart.Match(outHtmlText);
                if (m.Success) return m.Value;

                return null;
            }
        }

        private Dictionary<string, string> attributes = new Dictionary<string, string>();

        public Dictionary<string, string> Attributes
        {
            get
            {
                attributes.Clear();

                var fstBlank = new Regex(@"[ 　\t]");
                var mFstBlank = fstBlank.Match(outHtmlText);
                if (mFstBlank.Success == false) return attributes;

                var text = outHtmlText.Substring(mFstBlank.Index);
                text = text.Trim(new char[] { ' ', '　', '\t', '/', '>', }) + " ";

                var trimChars = new char[] { ' ', '　', '\t', };
                var trimChars2 = new char[] { ' ', '　', '\t', '=', '\'', '\"', };

                var regAttr = new Regex(@"[a-zA-Z][a-zA-Z\-_]{0,}([ 　\t]{0,}=[ 　\t]{0,}['""].*?['""]){0,1}(?=[ 　\t])");
                var matches = regAttr.Matches(text);
                foreach (Match m in matches)
                {
                    var index = m.Value.IndexOf("=");
                    if (index >= 0)
                    {
                        attributes.Add(m.Value.Substring(0, index).Trim(trimChars), m.Value.Substring(index).Trim(trimChars2));
                    }
                    else
                    {
                        attributes.Add(m.Value, "");
                    }
                }
                return attributes;
            }
            set
            {
                attributes = value;
            }
        }

        private Dictionary<string, string> appendDictionary = new Dictionary<string, string>();

        public Dictionary<string, string> AppendDictionary
        {
            get { return appendDictionary; }
            set
            {
                appendDictionary = value;
            }
        }

        public override string ToString()
        {
            switch (TagType)
            {
                case HtmlTagType.Start:
                    StringBuilder sb = new StringBuilder();
                    sb.Append("<");
                    sb.Append(Name);
                    foreach (var keyValue in attributes)
                    {
                        if (string.IsNullOrWhiteSpace(keyValue.Key) == false)
                        {
                            sb.Append(" ");
                            sb.Append(keyValue.Key);
                            if (string.IsNullOrEmpty(keyValue.Value) == false)
                            {
                                sb.Append("=\"");
                                sb.Append(keyValue.Value);
                                sb.Append("\"");
                            }
                        }
                    }
                    if (appendDictionary.Count > 0)
                    {
                        foreach (var keyValue in appendDictionary)
                        {
                            if (string.IsNullOrWhiteSpace(keyValue.Key) == false)
                            {
                                sb.Append(" ");
                                if (string.IsNullOrEmpty(keyValue.Value) == false)
                                {
                                    sb.Append(keyValue.Key);
                                    sb.Append("=\"");
                                    sb.Append(keyValue.Value);
                                    sb.Append("\"");
                                }
                            }
                        }
                    }
                    sb.Append(">");
                    return sb.ToString();
                case HtmlTagType.End:
                    return "</" + Name + ">";
                case HtmlTagType.Whole:
                    StringBuilder sb2 = new StringBuilder();
                    sb2.Append("<");
                    sb2.Append(Name);
                    foreach (var keyValue in Attributes)
                    {
                        if (string.IsNullOrWhiteSpace(keyValue.Key) == false)
                        {
                            sb2.Append(" ");
                            sb2.Append(keyValue.Key);
                            if (string.IsNullOrEmpty(keyValue.Value) == false)
                            {
                                sb2.Append("=\"");
                                sb2.Append(keyValue.Value);
                                sb2.Append("\"");
                            }
                        }
                    }
                    if (appendDictionary.Count > 0)
                    {
                        foreach (var keyValue in appendDictionary)
                        {
                            if (string.IsNullOrWhiteSpace(keyValue.Key) == false)
                            {
                                sb2.Append(" ");
                                if (string.IsNullOrEmpty(keyValue.Value) == false)
                                {
                                    sb2.Append(keyValue.Key);
                                    sb2.Append("=\"");
                                    sb2.Append(keyValue.Value);
                                    sb2.Append("\"");
                                }
                            }
                        }
                    }
                    sb2.Append("/>");
                    return sb2.ToString();
                default:
                    return "";
            }
        }
    }
}
